﻿using System;
using System.Collections.Generic;
using System.Collections;

namespace worldParser
{

    class CGroup : CWorldObject
    {
        CWorldArray children;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "children": 
                    children = new CWorldArray();
                    objstack.Push(children);
                    break;                
                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CTransform : CGroup
    {
        Point3D translation;
        Rotation3D rotation = new Rotation3D(0, 1, 0, 0);
        Point3D scale = new Point3D(1,1,1);

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "translation": translation = new Point3D(values); break;
                case "rotation": rotation = new Rotation3D(values); break;
                case "scale": scale = new Point3D(values); break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CSolid : CTransform
    {
        string name, model, author, constructor, description;
        CWorldObject boundingObject;
        CPhysics physics;        
        bool locked;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "name": name = values[0]; break;
                case "model": model = values[0]; break;
                case "author": author = values[0]; break;
                case "constructor": constructor = values[0]; break;
                case "description": description = values[0]; break;              
                case "physics": objstack.Push(physics); break;
                case "locked": locked = values[0][0] == 'T'; break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }

        public override void PostParamByName(string param, IWorldStackObject value)
        {
            switch (param)
            {
                case "boundingObject": boundingObject = (CWorldObject)value; break;
                case "physics": physics = (CPhysics) value; break;
                case "joint": /*old field, just pass thru*/break;
                default: base.PostParamByName(param, value); break;
            }
        }
    }    

    class CServo : CSolid
    {
        string type;
        float maxVelocity, maxForce, controlP, acceleration, position, minPosition, maxPosition, minStop, maxStop, springConstant, dampingConstant;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "type": type = values[0]; break;
                case "maxVelocity": maxVelocity = Float.Parse(values[0]); break;
                case "maxForce": maxForce = Float.Parse(values[0]); break;
                case "controlP": controlP = Float.Parse(values[0]); break;
                case "acceleration": acceleration = Float.Parse(values[0]); break;
                case "position": position = Float.Parse(values[0]); break;
                case "minPosition": minPosition = Float.Parse(values[0]); break;
                case "maxPosition": maxPosition = Float.Parse(values[0]); break;
                case "minStop": minStop = Float.Parse(values[0]); break;
                case "maxStop": maxStop = Float.Parse(values[0]); break;
                case "springConstant": springConstant = Float.Parse(values[0]); break;
                case "dampingConstant": dampingConstant = Float.Parse(values[0]); break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CDistanceSensor : CSolid
    {
        CWorldArray lookupTable;
        string type;
        int numberOfRays;
        float aperture, gaussianWidth;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "lookupTable": lookupTable = new CWorldArray();
                    objstack.Push(lookupTable); break;
                case "type": type = values[0]; break;
                case "numberOfRays": numberOfRays = int.Parse(values[0]); break;
                case "aperture": aperture = Float.Parse(values[0]); break;
                case "gaussianWidth": gaussianWidth = Float.Parse(values[0]); break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CLightSensor : CSolid
    {
        CWorldArray lookupTable;
        //CWorldArray colorFilter;
        bool        occlusion;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "lookupTable": lookupTable = new CWorldArray();
                    objstack.Push(lookupTable); break;
                case "occlusion": occlusion = values[0][0] == 'T'; break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CTouchSensor : CSolid
    {
        CWorldArray lookupTable;
        string type;        

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "lookupTable": lookupTable = new CWorldArray();
                    objstack.Push(lookupTable); break;
                case "type": type = values[0]; break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }
     
    class CReceiver : CSolid
    {
        string type;
        float aperture;
        int channel, baudRate, byteSize, bufferSize;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "aperture": aperture = Float.Parse(values[0]); break;
                case "channel": channel = int.Parse(values[0]); break;
                case "baudRate": baudRate = int.Parse(values[0]); break;
                case "byteSize": byteSize = int.Parse(values[0]); break;
                case "bufferSize": bufferSize = int.Parse(values[0]); break;
                case "type": type = values[0]; break;

                default: base.SetParamByName(objstack, param, values); break;
            }
        }
    }

    class CEmitter : CSolid
    {
        string type;
        float range, maxRange, aperture;
        int channel, baudRate, byteSize, bufferSize;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
            switch (param)
            {
                case "type": type = values[0]; break;
                case "range": range = Float.Parse(values[0]); break;
                case "maxRange": maxRange = Float.Parse(values[0]); break;
                case "aperture": aperture = Float.Parse(values[0]); break;
                case "channel": channel = int.Parse(values[0]); break;
                case "baudRate": baudRate = int.Parse(values[0]); break;
                case "byteSize": byteSize = int.Parse(values[0]); break;
                case "bufferSize": bufferSize = int.Parse(values[0]); break;

                default: base.SetParamByName(objstack,  param, values); break;
            }
        }
    }


    class CGPS : CSolid
    {
        string type;
        float resolution;

        public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
        {
          switch (param)
          {
              case "resolution": resolution = Float.Parse(values[0]); break;
              case "type": type = values[0]; break;

              default: base.SetParamByName(objstack, param, values); break;
          }
        }
    }

    class CCamera : CSolid
    {
      float  fieldOfView, width, height;
      bool display;
      string type;
      float near, far;
      Point2D windowPosition;
      int pixelSize;

      public override void SetParamByName(Stack<IWorldStackObject> objstack, string param, List<string> values)
      {
          switch (param)
          {
              case "fieldOfView": fieldOfView = Float.Parse(values[0]); break;
              case "width": width = Float.Parse(values[0]); break;
              case "height": height = Float.Parse(values[0]); break;
              case "type": type = values[0]; break;
              case "display": display = values[0][0] == 'T'; break;
              case "near": near = Float.Parse(values[0]); break;
              case "far": far = Float.Parse(values[0]); break;
              case "windowPosition": windowPosition = new Point2D(values); break;
              case "pixelSize": pixelSize = int.Parse(values[0]); break;

              default: base.SetParamByName(objstack, param, values); break;
          }
      }
    }

}